﻿using IPluginInterface;
using Qting.AOI.Serialize;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using YiNing.Tools;
using static Lixun.BaseParameters;

namespace Lixun
{
    [Serializable]
    public class MesPlugin : MarshalByRefObject, IAoiPlugin
    {
        public string Tag
        {
            get;
            private set;
        }

        public Version Version
        {
            get;
            private set;
        }

        public string Description
        {
            get;
            private set;
        }

        Service_LuxShare service_LuxShare;// = new Service_LuxShare();
        BaseParameters baseParameters;
        Parameters1 parameters1;
        Parameters2 parameters2;
        string f1 = "baseParameters.zyn", f2 = "parameters1.zyn", f3 = "parameters2.zyn";

        public MesPlugin()
        {
            Tag = "立讯Mes插件(立讯BU19-锦溪)";
            Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            Description = "立讯mes插件-多联板";
        }
        public PluginResult Init(params object[] args)
        {
            baseParameters = File.Exists(f1) ? JsonHelper.DeserializeByFile<BaseParameters>(f1) : new BaseParameters();
            parameters1 = File.Exists(f2) ? JsonHelper.DeserializeByFile<Parameters1>(f2) : new Parameters1();
            parameters2 = File.Exists(f3) ? JsonHelper.DeserializeByFile<Parameters2>(f3) : new Parameters2();
            baseParameters = baseParameters == null ? new BaseParameters() : baseParameters;
            parameters1 = parameters1 == null ? new Parameters1() : parameters1;
            parameters2 = parameters2 == null ? new Parameters2() : parameters2;
            service_LuxShare = new Service_LuxShare();

            if(baseParameters.ErrorCodes.Count == 0)
            {
                baseParameters.ErrorCodes = new List<ErrorCode>();
                var values = Enum.GetValues(typeof(ResultTypeCn));
                for (int i = 0; i < values.Length; i++)
                {
                    var oneEnum = values.GetValue(i).ToString();
                    ErrorCode errorCode = new ErrorCode();
                    errorCode.ErrorCodeIndex = i;
                    errorCode.ErrorCodeAOI = oneEnum;
                    errorCode.ErrorCodeMES = ((ResultType)i).ToString();
                    baseParameters.ErrorCodes.Add(errorCode);
                }
            }
            return new PluginResult();
        }

        public PluginResult Start(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            //aoiPcbs.pcb_name = "Start";
            return new PluginResult();
        }

        public PluginResult BeforeProductIn(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            //aoiPcbs.pcb_name = "BeforeProductIn";
            return new PluginResult();
        }
        public PluginResult ProductIn(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            PluginResult pluginResult = new PluginResult();
            // string res = "";
            // try
            // {
            //     if (parameters1 != null)
            //     {
            //         parameters1.WorkOrder = baseParameters.WorkOrder;
            //         parameters1.TerminalID = bDual ? baseParameters.TerminalID2 : baseParameters.TerminalID1;
            //         parameters1.MachineType = baseParameters.MachineType;
            //         parameters1.LaneNO = bDual ? "2" : "1";
            //         parameters1.ProgramName = aoiPcbs.pcb_name;
            //         parameters1.ToolingSN = "";
            //         string sn = "";
            //         foreach (var one in aoiPcbs.m_barcodeList)
            //         {
            //             sn += one.strBarcode + ",";
            //         }
            //         if (aoiPcbs.m_barcodeList.Count > 0 && sn.Length > 1) sn = sn.Remove(sn.Length - 1, 1);
            //         parameters1.PanelBarCode = sn;
            //     }
            //     string data = JsonHelper.Serialize(parameters1);
            //     res = service_LuxShare.getsn(data);
            // }
            // catch(Exception er)
            // {
            //     res = er.Message;
            //     LogHelper.WriteLog(string.Format("getsn data:{0} res:{1}", JsonHelper.Serialize(parameters1), res), er);
            //     pluginResult.Status = Status.Alarm;
            //     pluginResult.ErrorMsg = res;
            // }
            // LogHelper.WriteLog(string.Format("getsn data:{0} res:{1}", JsonHelper.Serialize(parameters1), res));
            // //MessageBox.Show("MES返回结果" + res);
            return pluginResult;
        }

        public PluginResult AfterProductIn(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            //aoiPcbs.pcb_name = "AfterProductIn";
            return new PluginResult();
        }
        public PluginResult BeforeProductOut(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            //aoiPcbs.pcb_name = "BeforeProductOut";

            return new PluginResult();
        }

        public PluginResult ProductOut(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            PluginResult pluginResult = new PluginResult();
            return pluginResult;
        }

        public PluginResult AfterProductOut(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            return new PluginResult();
        }

        public PluginResult Done(ref AoiPcbs aoiPcbs, bool bDual = false, params object[] args)
        {
            PluginResult pluginResult = new PluginResult();
            string res = "";
            try
            {
                if (parameters2 != null)
                {
                    parameters2.WorkOrder = baseParameters.WorkOrder;
                    parameters2.TerminalID = bDual ? baseParameters.TerminalID2 : baseParameters.TerminalID1;
                    parameters2.MachineType = baseParameters.MachineType;
                    parameters2.LaneNO = bDual ? "2" : "1";
                    parameters2.ProgramName = aoiPcbs.pcb_name;
                    try
                    {
                        string sn = aoiPcbs.m_barcodeList.Count > 0 ? aoiPcbs.m_barcodeList.FindLast(v => v.FunctionType == 3).strBarcode : "";

                        parameters2.ToolingSN = sn;
                    }
                    catch (Exception er)
                    {
                        parameters2.ToolingSN = "";
                    }
                    parameters2.CreateTime = aoiPcbs.create_time;
                    parameters2.ReviseEndTime = aoiPcbs.end_time;
                    parameters2.Panels = GetNgTestResult(aoiPcbs, out string testResult);
                    parameters2.TestResult = testResult;// aoiPcbs.is_error > 0 ? "FAIL" : (aoiPcbs.is_misjudge_2d > 0 || aoiPcbs.is_misjudge_advm > 0 || aoiPcbs.is_misjudge_ai > 0) ? "REPASS" : "PASS";
                }

                string data = JsonHelper.Serialize(parameters2);
                res = service_LuxShare.PostData(data);
            }
            catch (Exception er)
            {
                res = er.Message;
                LogHelper.WriteLog(string.Format("PostData data:{0} res:{1}", JsonHelper.Serialize(parameters2), res), er);
                pluginResult.Status = Status.Alarm;
                pluginResult.ErrorMsg = res;
            }
            LogHelper.WriteLog(string.Format("PostData data:{0} res:{1}", JsonHelper.Serialize(parameters2), res));
            return new PluginResult();
        }

        public void OpenSettingForm(params object[] args)
        {
            new Setting(baseParameters, parameters1, parameters2).ShowDialog();
        }
        private List<Panel> GetNgTestResult(AoiPcbs pcb, out string res)
        {
            res = "PASS";
            List<Panel> testItems = new List<Panel>();
            var unionPanels = pcb.m_barcodeList.FindAll(v => v.FunctionType == 1);

            if (unionPanels.Count == 0) // 如果为空那就默认一个主板
            {
                Panel panel = new Panel();
                try
                {
                    string sn = pcb.m_barcodeList.Count > 0 ? pcb.m_barcodeList.FindLast(v => v.FunctionType == 1).strBarcode : "";
                    panel.PanelBarCode = sn;
                }
                catch (Exception er) { }
                panel.Boards = new List<Board>();
                for (int i = 0; i < pcb.pcb_childen_number; i++)
                {
                    Board b = new Board();
                    try
                    {
                        tagBarcodeInfo barcodeInfo = pcb.m_barcodeList.Find(u => u.subBoard == i + 1 && u.FunctionType == 0);
                        b.BoardBarCode = barcodeInfo?.strBarcode;
                    }
                    catch (Exception er)
                    {
                    }
                    if (b.BoardBarCode == null) b.BoardBarCode = "";
                    b.Blocknumber = (i + 1).ToString();
                    #region 是否跳板
                    try
                    {
                        var skipBoadr = pcb.m_badBoardList.Find(u => u.Board == i + 1);
                        if (skipBoadr == null) b.SKIP = "N";
                        else b.SKIP = "Y";
                    }
                    catch (Exception er)
                    {

                    }
                    #endregion

                    #region 子板上的元件码
                    try
                    {
                        var codes = pcb.m_barcodeList.FindAll(u => u.subBoard == i + 1 && u.FunctionType == 2);
                        foreach (var one in codes) b.ComponmentID += one.strBarcode + ",";
                        if (b.ComponmentID.EndsWith(",")) b.ComponmentID = b.ComponmentID.Remove(b.ComponmentID.Length - 1);
                    }
                    catch (Exception er)
                    {
                        b.ComponmentID = "";
                    }
                    #endregion

                    List<Errordetail> errordetails = new List<Errordetail>();
                    int misjudgeCount = 0;
                    foreach (var one in pcb.results_2d)
                    {
                        if (one.IsMisjudge > 0)
                        {
                            misjudgeCount++;
                            continue;
                        }
                        if ( one.SubBoard != i + 1) continue;
                        Errordetail errordetail = new Errordetail();
                        errordetail.RefranceID = one.PartName;
                        try
                        {
                            string strNg = one.ResultString.Split(',')[0].Replace(",", "");
                            if (strNg.IndexOf('(') != -1) strNg = strNg.Substring(0, strNg.IndexOf('('));
                            var find = baseParameters.ErrorCodes.Find(v => v.ErrorCodeIndex == (int)Enum.Parse(typeof(ResultTypeCn), strNg));
                            errordetail.ErrorCode = find == null ? "" : find.ErrorCodeMES;
                        }
                        catch (Exception er)
                        {

                        }
                        errordetails.Add(errordetail);
                    }
                    b.Errordetails = errordetails.Count > 0 ? errordetails : null;

                    b.TestResult = errordetails.Count > 0 ? "FAIL" : (misjudgeCount > 0 && errordetails.Count == 0) ? "REPASS" : "PASS";

                    panel.Boards.Add(b);
                }
                panel.TestResult = pcb.results_2d.Count > 0 ? "FAIL" : "PASS";
                panel.ReviseResult = "PASS";
                if (panel.Boards.FindAll(v => v.TestResult.Equals("FAIL")).Count == pcb.pcb_childen_number)
                {
                    panel.ReviseResult = "FAIL";
                }
                else if (panel.Boards.FindAll(v => v.TestResult.Equals("REPASS")).Count > 0)
                {
                    panel.ReviseResult = "REPASS";
                }
                testItems.Add(panel);
            }

            else
            {
                for (int j = 0; j < unionPanels.Count; j++)
                {
                    var onePanel = unionPanels[j];

                    Panel panel = new Panel();
                    try
                    {
                        string sn = onePanel.strBarcode;
                        panel.PanelBarCode = sn;
                    }
                    catch (Exception er) { }
                    panel.Boards = new List<Board>();
                    int subBoardCount = pcb.pcb_childen_number / unionPanels.Count;

                    int start = j * subBoardCount, end = (j + 1) * subBoardCount;
                    for (int i = start; i < end; i++)
                    {
                        Board b = new Board();
                        b.Blocknumber = (i + 1).ToString().PadLeft(2, '0'); //i.ToString().PadLeft(3,'0')
                        try
                        {
                            tagBarcodeInfo barcodeInfo = pcb.m_barcodeList.Find(u => u.subBoard == i + 1 && u.FunctionType == 0 && u.unionBoard == onePanel.unionBoard);
                            b.BoardBarCode = barcodeInfo?.strBarcode;
                        }
                        catch (Exception er)
                        {
                        }
                        if (b.BoardBarCode == null) b.BoardBarCode = panel.PanelBarCode;
                        #region 是否跳板
                        try
                        {
                            var skipBoadr = pcb.m_badBoardList.Find(u => u.Board == i + 1 && u.UnionBoard == onePanel.unionBoard);
                            if (skipBoadr == null) b.SKIP = "N";
                            else b.SKIP = "Y";
                        }
                        catch (Exception er)
                        {

                        }
                        #endregion

                        #region 子板上的元件码
                        try
                        {
                            b.ComponmentID = "";
                            var codes = pcb.m_barcodeList.FindAll(u => u.subBoard == i + 1 && u.FunctionType == 2 && u.unionBoard == onePanel.unionBoard);
                            foreach (var one in codes) b.ComponmentID += one.strBarcode + ",";
                            if (b.ComponmentID.EndsWith(",")) b.ComponmentID = b.ComponmentID.Remove(b.ComponmentID.Length - 1);
                        }
                        catch (Exception er)
                        {
                            b.ComponmentID = "";
                        }
                        #endregion


                        List<Errordetail> errordetails = new List<Errordetail>();
                        int misjudgeCount = 0;
                        foreach (var one in pcb.results_2d)
                        {
                            if (one.UnionBoard != onePanel.unionBoard) continue;
                            if (one.UnionBoard == onePanel.unionBoard && one.SubBoard != i + 1) continue;
                            if (one.IsMisjudge > 0)
                            {
                                misjudgeCount++;
                                continue;
                            }
                            Errordetail errordetail = new Errordetail();
                            errordetail.RefranceID = one.PartName;
                            try
                            {
                                string strNg = one.ResultString.Split(',')[0].Replace(",", "");
                                if (strNg.IndexOf('(') != -1) strNg = strNg.Substring(0, strNg.IndexOf('('));
                                var find = baseParameters.ErrorCodes.Find(v => v.ErrorCodeIndex == (int)Enum.Parse(typeof(ResultTypeCn), strNg));
                                errordetail.ErrorCode = find == null ? "" : find.ErrorCodeMES;
                            }
                            catch (Exception er)
                            {

                            }
                            errordetails.Add(errordetail);
                        }
                        b.Errordetails = errordetails.Count > 0 ? errordetails : null;

                        b.TestResult = errordetails.Count > 0 ? "FAIL" : (misjudgeCount > 0 && errordetails.Count == 0) ? "REPASS" : "PASS";

                        panel.Boards.Add(b);
                    }
                    panel.TestResult = pcb.results_2d.Count > 0 ? "FAIL" : "PASS";
                    panel.ReviseResult = "PASS";
                    if (panel.Boards.FindAll(v => v.TestResult.Equals("FAIL")).Count == pcb.pcb_childen_number)
                    {
                        panel.ReviseResult = "FAIL";
                    }
                    else if (panel.Boards.FindAll(v => v.TestResult.Equals("REPASS")).Count > 0)
                    {
                        panel.ReviseResult = "REPASS";
                    }
                    testItems.Add(panel);
                }
            }

            if (testItems.FindAll(v => v.TestResult.Equals("FAIL")).Count == pcb.pcb_childen_number)
            {
                res = "FAIL";
            }
            else if (testItems.FindAll(v => v.TestResult.Equals("REPASS")).Count > 0)
            {
                res = "REPASS";
            }

            return testItems;
        }

        public PluginResult YiNing(ref AoiPcbs spiPcbs, params object[] args)
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            service_LuxShare?.Dispose();
        }

        public enum ResultType
        {
            OK = 0,//AOI端没有OK项，这里从aoi转换后要加1
            Default,
            BodySearch,
            PadSearch,
            Shift,
            SoderLess,
            SolderExcessive,
            SolderWelding,
            SolderNotReal,
            SolderOpen,
            Tombstand,
            MissingComponent,
            MultipleComponent,
            MixedComponent,
            FlipComponent,
            SolderShort,
            SickScreen,
            WrongPolarity,
            LeadFail,
            BrokenComponent,
            PinCrooked,
            MissingHeatSink,
            BackwardComponent,
            HighPosition,
            Broken,
        }

    }
}
